﻿using G.Model;
using G.Model.Enums;
using G.Runtime;

using System.Collections.Generic;

namespace Minesweeper
{
    public class MineSweeper
    {
        const string BOMB = "B";
        const string VALUE = "Value";
        
        struct P {
            public int x;
            public int y;
            public P(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }
        
        static MineSweeper()
        {
            NumberOfBombs = 1;
        }
        
        public static void Build(GameSpaceDef game)
        {
            game.Name = "MineSweeper";
            
            List<GameElementDef> elements = new List<GameElementDef>();
            for (int x = 0; x < game.Width; x++)
            {
                for (int y = 0; y < game.Height; y++)
                {
                    GameElementDef element = new GameElementDef(
                        game, new GameLocation(x, y));
                    element.MoveStratagy = MoveStratagyEnum.NO_MOVE;
                    element.Player = "Nothing";
                    element.Icon = "Button";
                    
                    game.GameElementDefs.Add(element);
                    elements.Add(element);
                }
            }
            List<GameElementDef> bombs = AssignBombs(elements);
            AssignValues(game, bombs);
            
        }
        
        public static int NumberOfBombs
        {
            get;
            set;
        }

        static List<GameElementDef> AssignBombs(List<GameElementDef> elements)
        {
            System.Random r = new System.Random();
            List<GameElementDef> list = new List<GameElementDef>();
            while(list.Count < NumberOfBombs)
            {
                GameElementDef element = elements[r.Next(elements.Count - 1)];
                
                if (list.Contains(element))
                {
                    continue;
                }
                
                element.Text = BOMB;
                list.Add(element);
            }
            
            return list;
        }
        
        static void AssignValues(GameSpaceDef pGameDef, List<GameElementDef> elements)
        {
            foreach (GameElementDef element in elements) 
            {
                List<GameElementDef> neigbors = 
                    GetNeiboringElements(pGameDef, element.Location);
                
                foreach (GameElementDef neigbor in neigbors) 
                {
                    if (neigbor.Text != BOMB)
                    {
                        int v = 0;
                        int.TryParse(neigbor.Text, out v);
                        v += 1;
                        neigbor.Text = "" + v;
                    }
                }
            }
        }
        
        static private List<GameElementDef> GetNeiboringElements(
            GameSpaceDef game, GameLocation cursor)
        {
            List<GameLocation> locations = new List<GameLocation>();
            P[] ps = new P[] 
            {
                new P(-1, -1), new P(+0, -1), new P(+1, -1),
                new P(-1, +0), new P(+1, +0),
                new P(-1, +1), new P(+0, +1), new P(+1, +1)
            };

            foreach (P p in ps) 
            {
                GameLocation l = new GameLocation(cursor.X + p.x, cursor.Y + p.y);
                locations.Add(l);
            }
            
            List<GameElementDef> result = new List<GameElementDef>();
            foreach (GameLocation  loc in locations) 
            {
                if (game.GameElementDefs.Contains(loc))
                {
                    GameElementDef def = game.GameElementDefs[loc];
                    result.Add(def);
                }
            }
            
            return result;
        }

        static public void RemoveSquares(
            GameSpace game, GameElement element)
        {
            RemoveSquaresLeft(game, element.Location, 10);
            RemoveSquaresRight(game, element.Location, 10);
            RemoveSquaresUp(game, element.Location, 10);
            RemoveSquaresDown(game, element.Location, 10);
        }

        static void RemoveSquaresLeft(
            GameSpace game, GameLocation start, int deep = 0)
        {
            int y = start.Y;
            for (int x = start.X; x >= 0; x--) 
            {
                GameElement e = game.Elements.Get(x, y);
                if (e.Text != "") 
                {
                    break;
                }
                e.Icon = "";
                if (deep > 0) 
                {
                    deep--;
                    RemoveSquaresUp(game, new GameLocation(x, y), deep);
                    RemoveSquaresDown(game, new GameLocation(x, y), deep);
                }
            }
        }
        
        static void RemoveSquaresRight(
            GameSpace game, GameLocation start, int deep = 0)
        {
            int y = start.Y;
            for (int x = start.X; x < game.Def.Width; x++) 
            {
                GameElement e = game.Elements.Get(x, y);
                if (e.Text != "") 
                {
                    break;
                }
                e.Icon = "";
                if (deep > 0) 
                {
                    deep--;
                    RemoveSquaresUp(game, new GameLocation(x, y), deep);
                    RemoveSquaresDown(game, new GameLocation(x, y), deep);
                }
            }
        }
        
        static void RemoveSquaresUp(
            GameSpace game, GameLocation start, int deep = 0)
        {
            int x = start.X;
            for (int y = start.Y; y >= 0; y--) 
            {
                GameElement e = game.Elements.Get(x, y);
                if (e.Text != "") 
                {
                    break;
                }
                e.Icon = "";
                if (deep > 0) 
                {
                    deep--;
                    RemoveSquaresLeft(game, new GameLocation(x, y), deep);
                    RemoveSquaresRight(game, new GameLocation(x, y), deep);
                }
            }
        }
        
        static void RemoveSquaresDown(
            GameSpace game, GameLocation start, int deep = 0)
        {
            int x = start.X;
            for (int y = start.Y; y < game.Def.Height; y++) 
            {
                GameElement e = game.Elements.Get(x, y);
                if (e.Text != "") 
                {
                    break;
                }
                e.Icon = "";
                if (deep > 0) 
                {
                    deep--;
                    RemoveSquaresLeft(game, new GameLocation(x, y), deep);
                    RemoveSquaresRight(game, new GameLocation(x, y), deep);
                }
            }
        }
        
    }
}

